package com.user.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.user.dao.WeatherDao;
import com.user.dao.restaurant.*;
import com.user.domain.Dish;
import com.user.domain.Restaurant;
import com.user.domain.User;
import com.user.mapper.DishMapper;
import com.user.mapper.OrderMapper;
import com.user.mapper.RestaurantMapper;
import com.user.mapper.UserMapper;
import com.user.service.RestaurantService;
import com.user.utils.PredictFutureSales;
import com.user.utils.R;
import com.user.utils.RecommendRestaurants;
import com.user.utils.WeatherFactorGenerator;
import org.springframework.stereotype.Service;
import weka.classifiers.functions.LinearRegression;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author YU
 * @Description 针对表【restaurant】的数据库操作Service实现
 * @Date 2024-02-05 17:55:05
 */
@Service
public class RestaurantServiceImpl extends ServiceImpl<RestaurantMapper, Restaurant> implements RestaurantService {

    private final ObjectMapper objectMapper = new ObjectMapper();
    @Resource
    DishMapper dishMapper;
    @Resource
    UserMapper userMapper;
    @Resource
    private RestaurantMapper restaurantMapper;
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private UserServiceImpl userServiceImpl;


    @Override
    public boolean isRestaurantNameExist(String name) {
        return false;
    }

    @Override
    public boolean isRestaurantIdExist(Integer id) {
        Restaurant restaurant = restaurantMapper.selectById(id);
        return restaurant != null;
    }

    @Override
    public R getRestaurantList(QueryPageRestaurant restaurant) {
        Page<Restaurant> mapPage = new Page<>(restaurant.getCurrent(), restaurant.getSize(), false);
        IPage<Restaurant> page = restaurantMapper.selectRestaurant(restaurant, mapPage);
        page.setTotal(restaurantMapper.selectRestaurantCount(restaurant));
        return R.ok().setData(page);
    }

    @Override
    public R getRestaurantsList(QueryPageRestaurant restaurant) {
        Page<Restaurant> mapPage = new Page<>(restaurant.getCurrent(), restaurant.getSize(), false);
        IPage<Restaurant> page = restaurantMapper.selectRestaurants(restaurant, mapPage);
        page.setTotal(restaurantMapper.selectRestaurantCount(restaurant));
        return R.ok().setData(page);
    }

    @Override
    public R getRestaurantMonthSales(QueryMonthSales queryMonthSales) {
        List<String> monthOrders = orderMapper.selectOrderByRestaurantId(queryMonthSales.getRestaurantId(), queryMonthSales.getDate());
        MonthSales monthSales = new MonthSales();
        if (monthOrders != null && !monthOrders.isEmpty()) {
            Integer totalSales = 0;
            Map<String, MonthSales.Dish> dishMap = new HashMap<>();
            for (String monthOrder : monthOrders)
                try {
                    Map<Integer, Integer> orderDetails = objectMapper.readValue(monthOrder, new TypeReference<Map<Integer, Integer>>() {
                    });
                    for (Map.Entry<Integer, Integer> entry : orderDetails.entrySet()) {
                        totalSales += entry.getValue();
                        String dishName = dishMapper.selectDishNameById(entry.getKey());
                        MonthSales.Dish dish = dishMap.getOrDefault(dishName, new MonthSales.Dish());
                        dish.setName(dishName);
                        if (dish.getNum() == null) dish.setNum(0);
                        dish.setNum(dish.getNum() + entry.getValue());
                        dishMap.put(dishName, dish);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            monthSales.setTotal(totalSales);
            monthSales.setDishList(new ArrayList<>(dishMap.values()));
        } else return R.error("没有数据");
        return R.ok().setData(monthSales);
    }

    @Override
    public R getRestaurantMonthlySales(Integer restaurantId) {
        List<MonthOrder> monthOrders = orderMapper.selectMonthlySalesByRestaurantId(restaurantId);
        Map<String, Integer> sortedMonthlySales = new LinkedHashMap<>();

        for (MonthOrder monthOrder : monthOrders) {
            String orderDetail = monthOrder.getOrderDetail();
            String month = monthOrder.getCreateTime();
            try {
                Map<Integer, Integer> orderDetails = objectMapper.readValue(orderDetail, new TypeReference<Map<Integer, Integer>>() {
                });
                for (Map.Entry<Integer, Integer> entry : orderDetails.entrySet())
                    sortedMonthlySales.put(month, sortedMonthlySales.getOrDefault(month, 0) + entry.getValue());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return R.ok().setData(sortedMonthlySales);
    }

    @Override
    public R createRestaurant(CreatRestaurant creatRestaurant) {
        boolean phoneRegistered = userServiceImpl.isPhoneRegistered(creatRestaurant.getPhone());
        if (phoneRegistered) return R.error("手机号已注册");
        User user = userServiceImpl.createUser(creatRestaurant.getPhone());
        userMapper.insert(user);
        Restaurant restaurant = new Restaurant();
        restaurant.setName(creatRestaurant.getRestaurantName());
        restaurant.setAddress(creatRestaurant.getRestaurantAddress());
        restaurant.setMaster(user.getId());
        restaurant.setCreateTime(new Date());
        restaurant.setState(1);
        if (save(restaurant)) return R.ok();
        return R.error("创建失败");
    }

    @Override
    public R getAllRestaurant() {
        List<Restaurant> restaurants = restaurantMapper.selectList(null);
        return R.ok().setData(restaurants);
    }

    @Override
    public R updateStatus(Integer restaurantId) {
        Restaurant restaurant = restaurantMapper.selectById(restaurantId);
        if (restaurant == null) return R.error("餐厅不存在");
        if (restaurant.getState() == 1) restaurant.setState(0);
        else restaurant.setState(1);
        updateById(restaurant);
        return R.ok();
    }

    @Override
    public R getAfterSales(Integer dishId) {
        //获取当前时间格式YYYY-mm-dd
        LocalDate currentDate = LocalDate.now();
        LocalDate dateAfterTwelveDays = currentDate.plusDays(12);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDate = currentDate.format(formatter);
        String dateAfter = dateAfterTwelveDays.format(formatter);
        try {
            Dish dish = dishMapper.selectById(dishId);
            List<AfterSaleDao> afterSales = new ArrayList<>();
            PredictFutureSales.attr();
            LinearRegression linearRegression = PredictFutureSales.trainModel("D:/Desktop/毕业设计/order-java/dish_dataset.arff");
            double initialScore = dish.getScore().doubleValue();
            double initialPrice = dish.getPrice().doubleValue();
            List<WeatherDao> weatherDaos = WeatherFactorGenerator.fetchWeatherData(29.5603, 106.5577, formattedDate, dateAfter);
            List<Double> futureSales = PredictFutureSales.predictFutureSalesEnhanced(linearRegression, initialScore, initialPrice, weatherDaos);

            for (int i = 0; i < futureSales.size(); i++) {
                AfterSaleDao afterSaleDao = new AfterSaleDao();
                double roundedFutureSales = Math.round(futureSales.get(i));
                afterSaleDao.setFutureSales(roundedFutureSales);
                afterSaleDao.setDate(weatherDaos.get(i).getDate());
                afterSales.add(afterSaleDao);
            }
            return R.ok().setData(afterSales);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.error("获取失败");

    }

    @Override
    public R recommendRestaurants(Integer userId) {
        List<com.user.dao.restaurant.RecommendRestaurants> recommendRestaurants1 = userMapper.selectByOrder();
        List<RestaurantRecommend> restaurantRecommends = restaurantMapper.selectRestaurantRecommend();
        try {
            List<com.user.dao.user.recommendation.Restaurant> restaurants = RecommendRestaurants.recommendRestaurants(userId, recommendRestaurants1, restaurantRecommends);
            return R.ok().setData(restaurants);
        } catch (IOException e) {
            return R.error("获取失败");
        }
    }
}




